def _impl_lib(ctx):
    obj_file_list = []

    print("输入源文件:", ctx.files.src_list)
    print("额外include文件夹:", ctx.files.include_path_list)
    print("输出可执行文件:", ctx.outputs.output_name)

    for src_file in ctx.files.src_list:
        obj_file = ctx.actions.declare_file("{}.obj".format(src_file.basename[:-4]))
        print("编译生成 {}".format(obj_file))

        args = ctx.actions.args()
        args.add("-o")
        args.add(obj_file)
        args.add("-c")
        args.add("-I")
        args.add("./")
        for header_dir in ctx.files.include_path_list:
            args.add("-I")
            args.add(header_dir)
        args.add(src_file)
        print("g++命令: $ g++", args)

        obj_file_list.append(obj_file)

        ctx.actions.run(
            executable = "/usr/bin/g++",
            arguments = [
                args,
            ],
            inputs = [src_file] + ctx.files.header_list,
            outputs = [obj_file],
        )

    print("已生成obj文件:", obj_file_list)
    args = ctx.actions.args()
    args.add("-rc")
    args.add(ctx.outputs.output_name)
    for obj_file in obj_file_list:
        args.add(obj_file)
    print("ar命令: $ar", args)
    ctx.actions.run(
        executable = "/usr/bin/ar",
        arguments = [
            args,
        ],
        inputs = obj_file_list,
        outputs = [ctx.outputs.output_name],
    )
    return [
        DefaultInfo(
            files = depset([ctx.outputs.output_name]),
        ),
    ]

make_lib = rule(
    implementation = _impl_lib,
    attrs = {
        "src_list": attr.label_list(allow_files = True, mandatory = True),
        "include_path_list": attr.label_list(allow_files = True, mandatory = True),
        "output_name": attr.output(mandatory = True),
        "header_list": attr.label_list(allow_files = True, mandatory = True),
    },
)

def _impl_exe(ctx):
    print("cpp源文件:", ctx.files.src_list)
    print("include额外文件夹:", ctx.files.include_dir_list)
    print("exe生成文件:", ctx.outputs.exe_name)
    print("准备好静态链接库:", ctx.files.lib_file_list)

    # I. 编译成obj文件
    args = ctx.actions.args()
    args.add("-o")
    obj_file = ctx.actions.declare_file("{}.obj".format(ctx.outputs.exe_name.basename[:-4]))
    args.add(obj_file)
    args.add("-c")
    args.add("-I")
    args.add("./")
    for header_dir in ctx.files.include_dir_list:
        args.add("-I")
        args.add(header_dir)
    for src_file in ctx.files.src_list:
        args.add(src_file)

    print("g++编译命令: $ g++", args)
    print("所有输入文件:", ctx.files.src_list + ctx.files.lib_file_list + ctx.files.header_list)

    ctx.actions.run(
        executable = "/usr/bin/g++",
        arguments = [
            args,
        ],
        inputs = ctx.files.src_list + ctx.files.lib_file_list + ctx.files.header_list,
        outputs = [obj_file],
    )

    # II. 生成exe文件
    # 无需额外添加include文件夹
    args = ctx.actions.args()
    args.add("-o")
    args.add(ctx.outputs.exe_name)

    # NOTE: 不加上-B参数, sandbox中无法运行
    args.add("-B")
    args.add("/usr/bin")
    args.add(obj_file)
    for lib_file in ctx.files.lib_file_list:
        args.add(lib_file)
    print("g++链接命令: $ g++", args)

    ctx.actions.run(
        executable = "/usr/bin/g++",
        arguments = [
            args,
        ],
        inputs = [obj_file] + ctx.files.lib_file_list,
        outputs = [ctx.outputs.exe_name],
    )

    return [
        DefaultInfo(
            files = depset([ctx.outputs.exe_name]),
        ),
    ]

make_exe = rule(
    implementation = _impl_exe,
    attrs = {
        "src_list": attr.label_list(allow_files = True, mandatory = True),
        "include_dir_list": attr.label_list(allow_files = True, mandatory = True),
        "exe_name": attr.output(mandatory = True),
        "header_list": attr.label_list(allow_files = True, mandatory = True),
        "lib_file_list": attr.label_list(allow_files = True, mandatory = True),
    },
)
